#include "main.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_uart.h"
#include "stm32f1xx_hal_iwdg.h"

#include "gdata.h"
#include "mflash.h"
int fputc(int ch, FILE *f) 
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
    HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    return ch;
}
void Uart1_Send(uint8_t* str,uint16_t len)
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
    HAL_UART_Transmit(&huart1, str, len, 0xFFFF);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
}
void Uart3_Send(uint8_t* str,uint16_t len)
{
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
    HAL_UART_Transmit(&huart3, str, len, 0xFFFF);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
}
uint8_t sendBuff[1024];
uint16_t baseAddr = 0;
//slave modbus node
void Uart3_DataDeal()
{
    uint8_t id = u3Buff[0];
    uint8_t fun  = u3Buff[1];
    uint16_t addr = u3Buff[2]<<8|u3Buff[3];
    uint16_t len  = u3Buff[4]<<8|u3Buff[5];
    uint8_t  bLen = u3Buff[6];
    uint16_t cCrc = Get_Crc16(u3Buff,u3Len-2);
    uint16_t rCrc = u3Buff[u3Len-2]|u3Buff[u3Len-1]<<8;
    if(cCrc != rCrc) return;
    if(id != gDataBase.addr_local) return;
    sendBuff[0] = id;sendBuff[1] = fun;sendBuff[2] = len*2;
    char* pAddr = (char*)&gDataBase;
    if(u3Len == 8 && fun == 0x03) //read regs
    {
        if( (addr >= 1) && (addr -1 + len*2) <= 255)
        {
            baseAddr = 1;
            if(!(addr%2)) baseAddr = addr - 1;
            else baseAddr = addr;
            for(uint16_t i=0;i<len;i++)
            {
                  sendBuff[3+i*2] = *(pAddr + baseAddr +i*2);
                  sendBuff[4+i*2] = *(pAddr + baseAddr +i*2-1);
            }
            cCrc = Get_Crc16(sendBuff,3+len*2);
            sendBuff[3+len*2] = cCrc &0xff;
            sendBuff[4+len*2] = cCrc>>8;
            Uart3_Send(sendBuff,5+len*2);
        }
    }
    else if(fun == 0x10 )//write regs
    {
        if( (addr >= 1) && (addr -1 + len*2) <= 128)
        {
            baseAddr = 1;
            sendBuff[0] = id;sendBuff[1] = fun;sendBuff[2] = addr >>8;sendBuff[3] = addr&0xff;
            sendBuff[4] = len>>8;sendBuff[5] = len&0xff;
            if(!(addr%2)) baseAddr = addr -1;
            else baseAddr = addr;
            char* pAddr = (char*)&gDataBase;
            for(uint16_t i=0;i<len;i++)
            {
                *(pAddr+baseAddr+i*2-1) = u3Buff[8+i*2];
                *(pAddr+baseAddr+i*2) =   u3Buff[7+i*2];
            }
            cCrc = Get_Crc16(sendBuff,6);
            sendBuff[6] = cCrc &0xff;
            sendBuff[7] = cCrc >> 8;
            HAL_FLASH_Unlock();
            uint32_t page;
            FLASH_EraseInitTypeDef erase;
            erase.Banks = FLASH_BANK_1;
            erase.NbPages = 1;
            erase.PageAddress = 0x801fc00;
            erase.TypeErase = FLASH_TYPEERASE_PAGES;
            HAL_FLASHEx_Erase(&erase,&page);
            uint16_t* pData = (uint16_t*)&gDataBase;
            for(int i=0;i<64;i++)
            {
                HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,0x801fc00+i*2,*pData);
                pData++;
            }
            HAL_FLASH_Lock();
            Uart3_Send(sendBuff,8);
        }
    }
}
//master modbus node
void Uart1_DataDeal()
{
    if(u1Len > 250 || u1Len < 6)
    {
        u1Len = 0;
        return;
    }
    uint8_t id = u1Buff[0];
    uint8_t fun  = u1Buff[1];
    uint8_t len = u1Buff[2];
    uint16_t cCrc = Get_Crc16(u1Buff,3+len);
    uint16_t rCrc = u1Buff[3+len]|u1Buff[4+len]<<8;
    if(cCrc != rCrc) return;
    uint8_t* pData = NULL;
    switch(currentSendIndex)
    {
        case 1:
            pData = (uint8_t*)&gDataBase.device1_total1;
            for(int i=0;i<len;i+=4)
            {
                *(pData+i) = u1Buff[6+i];
                *(pData+i+1) = u1Buff[5+i];
                *(pData+i+2) = u1Buff[4+i];
                *(pData+i+3) = u1Buff[3+i];
            }
            currentSendIndex = 2;
            break;
        case 2:
            pData = (uint8_t*)&gDataBase.device2_total1;
            for(int i=0;i<len;i+=4)
            {
                *(pData+i) = u1Buff[6+i];
                *(pData+i+1) = u1Buff[5+i];
                *(pData+i+2) = u1Buff[4+i];
                *(pData+i+3) = u1Buff[3+i];
            }
            currentSendIndex = 3;
            break;
        case 3:
            pData = (uint8_t*)&gDataBase.device3_total1;
            for(int i=0;i<len;i+=4)
            {
                *(pData+i) = u1Buff[6+i];
                *(pData+i+1) = u1Buff[5+i];
                *(pData+i+2) = u1Buff[4+i];
                *(pData+i+3) = u1Buff[3+i];
            }
            currentSendIndex = 4;
            break;
        case 4:
            pData = (uint8_t*)&gDataBase.device4_total1;
            for(int i=0;i<len;i+=4)
            {
                *(pData+i) = u1Buff[6+i];
                *(pData+i+1) = u1Buff[5+i];
                *(pData+i+2) = u1Buff[4+i];
                *(pData+i+3) = u1Buff[3+i];
            }
            currentSendIndex = 0;
            break;
    }
}

void Config_Init()
{
    gDataBase.device1_total1 = 0;
    gDataBase.device2_total1 = 0;
    gDataBase.device3_total1 = 0;
    gDataBase.device4_total1 = 0;
    uint16_t* pData = (uint16_t*)&gDataBase;
    uint32_t startAddr = VARIABLE_ADDRESS;
    for(int i=0;i<64;i++)
    {
        *pData++ = *(__IO uint32_t*)(startAddr);
        startAddr += 2;
    }
    //Set up defualt args
    if(gDataBase.addr_device1 == 0xffff)
    {
        HAL_FLASH_Unlock();
        uint32_t page;
        FLASH_EraseInitTypeDef erase;
        erase.Banks = FLASH_BANK_1;
        erase.NbPages = 1;
        erase.PageAddress = 0x801fc00;
        erase.TypeErase = FLASH_TYPEERASE_PAGES;
        HAL_FLASHEx_Erase(&erase,&page);
        pData = (uint16_t*)&gDefault_config;
        startAddr = 0x801fc00;
        for(int i=0;i<64;i++)
        {
            HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,startAddr,*pData);
            pData++;
            startAddr +=2;
        }
        HAL_FLASH_Lock();
        HAL_NVIC_SystemReset();
    }
    if(gDataBase.local_baud != 9600 && gDataBase.local_baud != 19200 && gDataBase.local_baud != 115200)
    {
        gDataBase.local_baud = 9600;
    }
    if(gDataBase.device_baud != 9600 && gDataBase.device_baud != 19200 && gDataBase.device_baud != 115200)
    {
        gDataBase.device_baud = 9600;
    }
    if(gDataBase.addr_local >= 255 || gDataBase.addr_local == 0)
    {
        gDataBase.addr_local = 2;
    }
    
}
uint16_t Get_Crc16(uint8_t *CmmBuf, uint8_t Len)
{
    uint16_t crc = 0xFFFF;
    unsigned char i;
    unsigned char j;
    j = 0;
    while(j < Len)
    {
        crc ^= CmmBuf[j];
        for(i=0; i < 8; i++)
        {
            if(crc & 0x01)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
        j++;
    }
    CmmBuf[j] = crc % 0x100; //校验和从长度算起，长度为长度减3
    CmmBuf[j + 1] = crc / 0x100;
    return crc;
}

void Uart1_Callback()
{
    static uint16_t temp = 0;
    if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET))  
    {   
        __HAL_UART_CLEAR_IDLEFLAG(&huart1); 
        huart1.Instance->SR;  
        huart1.Instance->DR;         
        HAL_UART_DMAStop(&huart1);  
        temp = huart1.hdmarx->Instance->CNDTR;
        u1Len =  1024 - temp;
        osSemaphoreRelease(semUart1Handle);
        HAL_UART_Receive_DMA(&huart1,u1Buff,1024);
    }  
}
void Uart3_Callback()
{
    static uint16_t temp1 = 0;
    if((__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE) != RESET))  
    {   
        __HAL_UART_CLEAR_IDLEFLAG(&huart3); 
        huart3.Instance->SR;  
        huart3.Instance->DR;         
        HAL_UART_DMAStop(&huart3);  
        temp1 = huart3.hdmarx->Instance->CNDTR;
        u3Len =  1024 - temp1;
        osSemaphoreRelease(semUart3Handle);
        HAL_UART_Receive_DMA(&huart3,u3Buff,1024);
    }  
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    //HAL_IWDG_Refresh(&hiwdg); 
    for(int i=0;i<8;i++)
    {
        adc_average[i] = 0;
        for(int j=0;j<5;j++)
        {
            adc_average[i] += adc_value[j*8+i];
        }
    }
}


